package com.example.greedysnake.slice;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.*;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;


import java.util.LinkedList;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

public class MainAbilitySlice extends AbilitySlice {
    private HiLogLabel c_hell=new HiLogLabel(HiLog.LOG_APP,0x0908,"D.T Sofware");

    private LinkedList <Snake> snakes=new LinkedList<Snake>();
    private Food food;
    private DrawComponment drawComponment;
    private boolean alive;
    private static final int GAMEFRAME_HEIGHT=320;
    private static final int GAMEFRAME_WIDTH=320;
    private Timer timer;
    private int DIRECTION;
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        initSnakes();
        initUI();
        snakeRun();
    }
    private void initSnakes(){
        DIRECTION=-1;
        snakes.add(new Snake(new Point(40,60)));
        food =new Food(new Point(120,180));

        alive=true;
    }
    private void initUI(){
        ComponentContainer cc=new PositionLayout(this);
        cc.setWidth(ComponentContainer.LayoutConfig.MATCH_PARENT);
        cc.setHeight(ComponentContainer.LayoutConfig.MATCH_PARENT);
        ShapeElement element1=new ShapeElement();
        element1.setRgbColor(new RgbColor(0,0,0));
        cc.setBackground(element1);

        ShapeElement element2=new ShapeElement();

        drawComponment=new DrawComponment(this);

        drawComponment.setTop(75);
        drawComponment.setLeft(75);
        drawComponment.setWidth(GAMEFRAME_WIDTH);
        drawComponment.setHeight(GAMEFRAME_HEIGHT);
        element2.setRgbColor(new RgbColor(255,255,255));
        drawComponment.setBackground(element2);

        cc.addComponent(drawComponment);

        Button btn=new Button(this);
        btn.setTop(395);
        btn.setLeft(180);
        btn.setText("restart");
        btn.setTextColor(new Color(0xFFDCDCDC));
        btn.setTextSize(40);

        btn.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                getUITaskDispatcher().asyncDispatch(() -> {
                    //timer.cancel();
                    snakes.clear();
                    initSnakes();
                    //initUI();
                    //snakeRun();
                    drawComponment.invalidate();//重新绘制
                });
            }
        });
        cc.addComponent(btn);
        super.setUIContent(cc);
    }
    private void snakeRun(){

        timer=new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                getUITaskDispatcher().asyncDispatch(() -> {
                    moveSnake();
                    dead();
                    drawComponment.invalidate();
                });
            }
        },0,750);
    }
    private void moveSnake(){
        if(alive)  { //当小蛇活着的时候 移动  死了就不动了

            switch(DIRECTION) {

                case 1://左
                    if(snakes.getLast().point.getPointX()-20<0) //超界
                        snakes.add(new Snake(new Point(GAMEFRAME_WIDTH-snakes.getLast().WIDTH,snakes.getLast().point.getPointY())));
                    else snakes.add(new Snake(new Point(snakes.getLast().point.getPointX()-20,snakes.getLast().point.getPointY())));
                    break;
                case -1://右
                    if(snakes.getLast().point.getPointX()+20==GAMEFRAME_WIDTH)
                        snakes.add(new Snake(new Point(0,snakes.getLast().point.getPointY())));
                    else snakes.add(new Snake(new Point(snakes.getLast().point.getPointX()+20,snakes.getLast().point.getPointY())));

                    break;
                case 2://上
                    if(snakes.getLast().point.getPointY()-20<0)
                        snakes.add(new Snake(new Point(snakes.getLast().point.getPointX(),GAMEFRAME_HEIGHT-snakes.getLast().HEIGHT)));
                    else snakes.add(new Snake(new Point(snakes.getLast().point.getPointX(),snakes.getLast().point.getPointY()-20)));

                    break;
                case -2://下
                    if(snakes.getLast().point.getPointY()+20==GAMEFRAME_HEIGHT)
                        snakes.add(new Snake(new Point(snakes.getLast().point.getPointX(),0)));
                    else snakes.add(new Snake(new Point(snakes.getLast().point.getPointX(),snakes.getLast().point.getPointY()+20)));

                    break;

                default: ;
            }
            if(changeSize()) snakes.removeFirst();	//如果遇到食物，则不删除第一个结点
           //drawComponment.invalidate();
        }
    }
    private boolean changeSize(){//蛇吃食物
       // return true;
        if(snakes.getLast().point.equals(food.point)){
            Random ran=new Random();
            do {
                int x = ran.nextInt(GAMEFRAME_WIDTH / 20) * 20;
                int y = ran.nextInt(GAMEFRAME_HEIGHT / 20) * 20;
                food.point = new Point(ran.nextInt(GAMEFRAME_WIDTH / 20) * 20, ran.nextInt(GAMEFRAME_HEIGHT / 20) * 20);
            }while(isFoodCreatInSnake(food.point));//防止在蛇体内生成
            return false;
        }
        else return true;
    }
    private boolean isFoodCreatInSnake(Point point){
        for(Snake s:snakes){
            if(s.point.equals(point))
                return true;
        }
        return false;
    }

    private void dead(){
        for(int i=0;i<snakes.size()-1;i++){
            if(snakes.getLast().point.equals(snakes.get(i).point)){
                alive=false;
                timer.cancel();
            }
        }
    }


    @Override
    public void onActive() {
        super.onActive();
    }
    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
    class Snake {
        static final int WIDTH=20;
        static final int HEIGHT=20;
        Point point =null;
        Snake(Point p){
            point=p;
        }

    }
    class Food{

        Point point=null;
        static final int width=20;
        static final int height=20;

        Food(Point p) {
            this.point=p;
        }
    }


    class DrawComponment extends Component implements Component.DrawTask, Component.TouchEventListener {
        float starX, starY, offsetX, offsetY;
        HiLogLabel hiLogLabel=new HiLogLabel(HiLog.LOG_APP,0x0900,"D.T Sofware");
        public DrawComponment(Context context) {
            super(context);
            //添加绘制任务
            addDrawTask(this);
            //设置TouchEvent监听
            setTouchEventListener(this);
        }

        @Override
        public void onDraw(Component component, Canvas canvas) {
            Paint paint=new Paint();
            paint.setColor(Color.GRAY);
            for(Snake s:snakes){//draw snake
                canvas.drawRect(new RectFloat(s.point.getPointX(),s.point.getPointY(),s.point.getPointX()+ Snake.HEIGHT,s.point.getPointY()+ Snake.WIDTH),paint);
            }
            Paint paint1=new Paint();
            paint1.setColor(Color.RED);
            canvas.drawRect(new RectFloat(food.point.getPointX(),food.point.getPointY(),food.point.getPointX()+ Food.width,food.point.getPointY()+ Food.height),paint1);
        }
        @Override
        public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
            MmiPoint point = touchEvent.getPointerScreenPosition(0);
            switch (touchEvent.getAction()) {
                case TouchEvent.PRIMARY_POINT_DOWN:
                    starX = point.getX();
                    starY = point.getY();
                    break;
                case TouchEvent.PRIMARY_POINT_UP:
                    offsetX = point.getX() - starX;
                    offsetY = point.getY() - starY;
                    if (Math.abs(offsetX) > Math.abs(offsetY)) {
                        if (offsetX < -5) {
                            HiLog.info(hiLogLabel, "left");
                            DIRECTION=1;

                        } else if (offsetX > 5) {
                            HiLog.info(hiLogLabel, "right");
                            DIRECTION=-1;

                        }
                    } else {
                        if (offsetY < -5) {
                            HiLog.info(hiLogLabel, "up");
                            DIRECTION=2;

                        } else if (offsetY > 5) {
                            HiLog.info(hiLogLabel, "down");
                            DIRECTION=-2;

                        }
                    }
                    break;
            }
            HiLog.info(c_hell,"move");

            invalidate();
            return true;
        }
    }

}
